package identify

import (
	"encoding/base64"
	"fmt"
)

// InitParams 识别模型初始化参数
type InitParams struct {
	WorkPath     string      // 识别模型工作路径
	UseProcessor Processor   // 使用的处理器
	MaxThreadNum int         // 最大使用线程数（仅UseProcessor == CPU可配置）
	AiKey        string      // SO初始化密钥
	FeatMode     FeatureMode // 特征初始化模式
}

func (p *InitParams) Clone() *InitParams {
	if p == nil {
		return nil
	}
	return &InitParams{
		WorkPath:     p.WorkPath,
		MaxThreadNum: p.MaxThreadNum,
		AiKey:        p.AiKey,
		FeatMode:     p.FeatMode,
	}
}

func (p *InitParams) String() string {
	if p == nil {
		return "nil"
	}
	return fmt.Sprintf(
		"{WorkPath: %s, MaxThreadNum: %d, AiKey: %s, FeatMode: %d}",
		p.WorkPath,
		p.MaxThreadNum,
		p.AiKey,
		p.FeatMode,
	)
}

// ImageAreaInfo 图像裁剪区域绝对坐标信息
type ImageAreaInfo struct {
	X0, Y0 int // 图像截取左上角X,Y坐标
	X1, Y1 int // 图像截取右上角X,Y坐标
	X2, Y2 int // 图像截取右下角X,Y坐标
	X3, Y3 int // 图像截取左下角X,Y坐标
}

func (p *ImageAreaInfo) Clone() *ImageAreaInfo {
	if p == nil {
		return nil
	}
	return &ImageAreaInfo{
		X0: p.X0, Y0: p.Y0,
		X1: p.X1, Y1: p.Y1,
		X2: p.X2, Y2: p.Y2,
		X3: p.X3, Y3: p.Y3,
	}
}

func (p *ImageAreaInfo) String() string {
	if p == nil {
		return "nil"
	}
	return fmt.Sprintf(
		"{0:(%d, %d), 1:(%d, %d), 2:(%d, %d), 3:(%d, %d)}",
		p.X0, p.Y0,
		p.X1, p.Y1,
		p.X2, p.Y2,
		p.X3, p.Y3,
	)
}

// ImageInfo 识别图像信息
type ImageInfo struct {
	Data []byte         // 图像资源
	Area *ImageAreaInfo // 图像裁剪区域绝对坐标信息（空指针将不对图像裁剪）
}

func (p *ImageInfo) Clone() *ImageInfo {
	if p == nil {
		return nil
	}
	res := &ImageInfo{
		Data: make([]byte, len(p.Data)),
		Area: p.Area.Clone(),
	}
	copy(res.Data, p.Data)
	return res
}

func (p *ImageInfo) String() string {
	if p == nil {
		return "nil"
	}
	return fmt.Sprintf(
		"{ImageData: %s, ImageArea: %s}",
		base64.StdEncoding.EncodeToString(p.Data),
		p.Area.String(),
	)
}

// RecordID 识别ID类型
type RecordID = int64

// YcAttri YC类别结构体定义,YC类别输出
type YcAttri struct {
	Score    float32 // YC识别绝对打分
	RefScore float32 // YC的相对打分
	Code     string  // YC编码
}

func (p *YcAttri) Clone() *YcAttri {
	if p == nil {
		return nil
	}
	return &YcAttri{
		Score:    p.Score,
		RefScore: p.RefScore,
		Code:     p.Code,
	}
}

func (p *YcAttri) String() string {
	if p == nil {
		return "nil"
	}
	return fmt.Sprintf(
		"{Score: %.6f, RefScore: %.6f, YoYoCode: %s}",
		p.Score, p.RefScore, p.Code,
	)
}

// Feature 特征信息结构体定义
type Feature struct {
	Mode FeatureMode // 特征模式
	Data []float32   // 特征信息列表
}

func (p *Feature) Clone() *Feature {
	if p == nil {
		return nil
	}
	res := &Feature{
		Mode: p.Mode,
		Data: make([]float32, len(p.Data)),
	}
	copy(res.Data, p.Data)
	return res
}

func (p *Feature) String() string {
	if p == nil {
		return "nil"
	}
	return fmt.Sprintf(
		"{FeatureMode: %d, FeatData: %v}",
		p.Mode, p.Data,
	)
}

// ProcessOutput 识别引擎输出结构体
type ProcessOutput struct {
	MagicCode int32      // 模型版本代号
	ID        RecordID   // 单次识别唯一ID
	YcList    []*YcAttri // YC列表,按照绝对分从高到低进行排序
	FeatList  []*Feature // 特征类目列表
	Duration  int64      // 识别耗时（毫秒）
}

func (p *ProcessOutput) Clone() *ProcessOutput {
	if p == nil {
		return nil
	}
	res := &ProcessOutput{
		MagicCode: p.MagicCode,
		ID:        p.ID,
		YcList:    make([]*YcAttri, 0, len(p.YcList)),
		FeatList:  make([]*Feature, 0, len(p.FeatList)),
		Duration:  p.Duration,
	}
	for _, v := range p.YcList {
		res.YcList = append(res.YcList, v.Clone())
	}
	for _, v := range p.FeatList {
		res.FeatList = append(res.FeatList, v.Clone())
	}
	return res
}

func (p *ProcessOutput) String() string {
	if p == nil {
		return "nil"
	}
	return fmt.Sprintf(
		"{MagicCode: %d, ID: %d, YcList: %v, FeatList: %v, Duration: %d}",
		p.MagicCode, p.ID, p.YcList, p.FeatList, p.Duration,
	)
}
